package com.orm.session;

import com.orm.executor.DefaultExecutor;
import com.orm.executor.Executor;
import com.orm.mapping.Configuration;
import com.orm.mapping.MapperStatement;
import com.orm.proxy.MapperProxy;
import com.orm.util.ClassUtil;
import lombok.Data;

import javax.sql.DataSource;
import java.lang.reflect.Proxy;
import java.util.List;

/**
 * 会话，根据传入参数 获得 mapper 代理对象
 *
 * session 其实也能执行sql 语句，但这里暂时不实现
 *
 * 返回的代理对象 mapper 必须持有sqlsession
 */
@Data
public class DefaultSqlSession  implements SqlSession{
	protected Executor executor;  //执行器
	
	protected Configuration config;
	
	public DefaultSqlSession() {
	}
	
	public DefaultSqlSession(Configuration config, DataSource dataSource) {
		this.config = config;
		this.executor = new DefaultExecutor(dataSource);
	}
	
	@Override
	public Configuration getConfiguration() {
		return this.config;
	}
	
	/**
	 * 返回目标接口类的代理对象mapper
	 *
	 * @param clazz 接口类class
	 * @param <T>
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T> T getMapper(Class<T> clazz) {
		String interfaceName = clazz.getName();
		if (config.getMapperCache().containsKey(interfaceName)) {  // 如果这个类已经缓存过，则返回缓存对象，否则创建代理对象
			return (T) config.getMapperCache().get(interfaceName);
		}
		
		Object proxyObj = Proxy.newProxyInstance(ClassUtil.getClassLoader(), new Class[]{clazz}, new MapperProxy(this,interfaceName));
		config.getMapperCache().putIfAbsent(interfaceName, proxyObj);  // 加入缓存
		return (T) proxyObj;
	}
	
	
	// 插入单个返回主键
	public int insert(MapperStatement mapperStatement, Object[] args) {
		int keyId = executor.insert(mapperStatement, args);
		return keyId;
	}
	
	public int update(MapperStatement mapperStatement, Object[] args) {
		int update = executor.update(mapperStatement, args);
		return update;
	}
	
	public int selectCount(MapperStatement mapperStatement, Object[] args) {
		return executor.selectCount(mapperStatement, args);
	}
	
	public Object selectOne(MapperStatement mapperStatement, Object[] args) {
		return executor.selectOne(mapperStatement, args);
	}
	
	public List<Object> selectList(MapperStatement mapperStatement, Object[] args) {
		return executor.selectList(mapperStatement, args);
	}
}
